package com.edu.robot.modules.im.service.impl;

import cn.hutool.core.thread.ThreadFactoryBuilder;
import cn.hutool.core.util.IdUtil;
import com.edu.chat.facade.facade.SessionFacade;
import com.edu.chat.facade.model.dto.SceneInfoDTO;
import com.edu.chat.facade.model.dto.SendMessageDTO;
import com.edu.chat.facade.model.dto.SessionInfoDetailDTO;
import com.edu.chat.facade.model.enums.MsgTypeEnum;
import com.edu.robot.common.constants.IMConstant;
import com.edu.robot.common.service.RedisUtil;
import com.edu.robot.core.enums.NotifyMsgEnum;
import com.edu.robot.core.model.APICallback;
import com.edu.robot.core.model.QueryContext;
import com.edu.robot.core.service.ModelManger;
import com.edu.robot.core.service.RobotService;
import com.edu.robot.model.R;
import com.edu.robot.model.enums.ResultCodeEnum;
import com.edu.robot.model.error.BizException;
import com.edu.robot.modules.im.controller.vo.MessageVO;
import com.edu.robot.modules.im.service.IMService;
import com.edu.robot.modules.im.service.MessageManger;
import com.edu.robot.modules.robot.dto.RobotInfoDTO;
import com.edu.robot.modules.robot.service.CrRobotService;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.concurrent.*;

import static java.util.concurrent.TimeUnit.SECONDS;


/**
 * @program: KQAIA
 * @description:
 * @author: 无恙
 * @create: 2025-03-30 18:43
 **/

@Component
@Slf4j
public class IMServiceImpl implements IMService {

	@DubboReference(interfaceClass = SessionFacade.class,check = false)
	private SessionFacade sessionFacade;

	@Autowired
	private CrRobotService crRobotService;

	@Autowired
	private RedisUtil redisUtil;

	@Autowired
	private MessageManger messageManger;

	@Autowired
	private RobotService robotService;

	@Autowired
	public ModelManger modelManger;

	private static final Executor asyncTitleExecutor =
			new ThreadPoolExecutor(2, 5, 60L, SECONDS, new LinkedBlockingQueue<>(100));

	@Override
	public void sendMessage(MessageVO messageVO) {
		log.info("IMServiceImpl.sendMessage:{}",messageVO);

		//根据会话ID 获取会话信息
		QueryContext queryContext = new QueryContext();
		queryContext.setUserInput(messageVO.getContent());
		queryContext.setSessionId(messageVO.getSessionId());
		queryContext.setSearchEnable(messageVO.getOpenSearch());
		queryContext.setUserId(messageVO.getUserId());
		queryContext.setTenantId(messageVO.getTenantId());

		storeMessage(messageVO);

		//是否命中缓存
		final String sessionKey = IMConstant.SESSION_REDIS_KEY+messageVO.getSessionId();

		SessionInfoDetailDTO sessionInfo = redisUtil.get(sessionKey, SessionInfoDetailDTO.class);

		if(sessionInfo == null){

			//从数据库中获取会话信息
			sessionInfo = sessionFacade.getSessionInfo(messageVO.getSessionId(), messageVO.getTenantId());

			if(sessionInfo == null){
				throw new BizException(ResultCodeEnum.DATABASE_ERROR,"会话信息不存在");
			}

			//设置会话信息到redis中
			redisUtil.set(sessionKey,sessionInfo,60*5);
		}


		queryContext.setSessionInfoDetailDTO(sessionInfo);

		//获取聊天窗信息
		SceneInfoDTO sceneInfo = sessionInfo.getSceneInfo();

		if(sceneInfo == null){
			throw new BizException(ResultCodeEnum.DATABASE_ERROR,"聊天窗信息不存在");
		}


		final String robotKey= IMConstant.ROBOT_CONFIG_REDIS_KEY+sceneInfo.getRobotId();

		RobotInfoDTO robotInfoDTO = redisUtil.get(robotKey, RobotInfoDTO.class);

		if(robotInfoDTO == null){
			//从数据库中获取机器人信息
			R<RobotInfoDTO> robot = crRobotService.getRobot(Long.valueOf(sceneInfo.getRobotId()));
			if(!robot.isSuccess() || robot.getData() == null){
				throw new BizException(ResultCodeEnum.DATABASE_ERROR,"机器人配置信息不存在");
			}
			robotInfoDTO = robot.getData();
			//设置机器人信息到redis中
			redisUtil.set(robotKey,robotInfoDTO,60*5);
		}

		queryContext.setRobotId(sceneInfo.getRobotId());
		queryContext.setRobotInfoDTO(robotInfoDTO);

		APICallback apiCallback = messageManger.sendStreamMessage(messageVO.getSessionId(), messageVO.getUserId(), sceneInfo.getRobotId(), messageVO.getTenantId());
		queryContext.setApiCallback(apiCallback);

		//判断是否是首次提问
		if(messageVO.getFirstMessage()){
			generateSessionName(queryContext);
		}

		robotService.robotQuery(queryContext);

	}

	private void storeMessage(MessageVO messageVO) {

			//存储用户提问
			SendMessageDTO sendMessageDTO = new SendMessageDTO();
			sendMessageDTO.setContent(messageVO.getContent());
			sendMessageDTO.setSessionId(messageVO.getSessionId());
			sendMessageDTO.setUserId(messageVO.getUserId());
			sendMessageDTO.setRobotId(messageVO.getRobotId());
			sendMessageDTO.setTenantId(messageVO.getTenantId());
			sendMessageDTO.setMsgType(MsgTypeEnum.USER.getCode());
			sendMessageDTO.setMessageId(IdUtil.getSnowflakeNextIdStr());
			sendMessageDTO.setTimestamp(System.currentTimeMillis());
			messageManger.insertMsg(sendMessageDTO);
	}

	//生成会话名称
	private void generateSessionName(QueryContext queryContext) {
		//用户首次提问，总结用户意图，生成会话title
		CompletableFuture.runAsync(() -> {

			try {
				String title = modelManger.titleRecognition(queryContext.getUserInput());
				APICallback callback = queryContext.getApiCallback();

				//去除空格，双引号
				title = title.replaceAll("\\s+","").replaceAll("\"","");

				log.info("generateSessionName res:{}",title);
				callback.onEvent(NotifyMsgEnum.TITLE,title);
//				//更新会话title
				sessionFacade.updateSessionName(queryContext.getSessionId(), title, queryContext.getTenantId());
			}catch (Exception e){
				log.error("generateSessionName error:{}",e.getMessage());
			}

		},asyncTitleExecutor);
	}

}
